package com.budwk.app.sqfw.services.datamange.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.budwk.app.common.config.AppException;
import com.budwk.app.sqfw.dto.onlineExcel.SqfwExcelOnlineAllDTO;
import com.budwk.app.sqfw.dto.onlineExcel.SqfwFormSummaryOnlineDTO;
import com.budwk.app.sqfw.models.*;
import com.budwk.app.sqfw.services.SqfwFormsummaryNewService;
import com.budwk.app.sqfw.services.datamange.DataMangeCityService;
import com.budwk.app.sqfw.services.datamange.DataMangeCommunityService;
import com.budwk.app.sqfw.services.datamange.DataMangeDistrictCheckService;
import com.budwk.app.sqfw.services.datamange.DataMangeDistrictService;
import com.budwk.app.sqfw.utils.CommunityDataCleanUtils;
import com.budwk.app.sqfw.vo.SqfwDataMangeCheckVO;
import com.budwk.app.sqfw.vo.SqfwDataMangeVO;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.util.ThreadPoolExecutorUtil;
import com.budwk.starter.common.page.Pagination;
import com.budwk.starter.common.result.ResultCode;
import com.budwk.starter.database.service.BaseServiceImpl;
import com.budwk.starter.security.utils.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.random.R;
import org.nutz.plugins.wkcache.annotation.CacheRemove;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@IocBean(args = {"refer:dao"})
public class DataMangeDistrictCheckServiceImpl extends BaseServiceImpl<Sqfw_datamange_district_check> implements DataMangeDistrictCheckService {
    public DataMangeDistrictCheckServiceImpl(Dao dao) {
        super(dao);
    }

    @Inject
    private SysUserService sysUserService;

    @Inject
    private SqfwFormsummaryNewService sqfwFormsummaryNewService;

    @Inject
    private DataMangeCommunityService dataMangeCommunityService;

    @Inject
    private DataMangeDistrictService dataMangeDistrictService;

    @Inject
    private DataMangeCityService dataMangeCityService;

    @Override
    public Pagination page(SqfwDataMangeCheckVO bean) {
        if (null == bean) {
            bean = new SqfwDataMangeCheckVO();
        }
        long startTime = System.currentTimeMillis();
        // 构造查询条件
        Criteria criteria = buildQueryCond(bean);
        log.info("DataMangeStreetCheckServiceImpl-list-SQL: {}", criteria.toString());
        Pagination pagination = dataMangeCommunityService.listPage(bean.getPageNo(), bean.getPageSize(), criteria);
        log.info("DataMangeStreetCheckServiceImpl-list-耗时: {}ms", System.currentTimeMillis() - startTime);
        return pagination;
    }

    @Override
    @Aop(TransAop.READ_COMMITTED)
    public SqfwDataMangeCheckVO check(SqfwDataMangeCheckVO bean) {
        if (null == bean || ObjectUtils.isEmpty(bean.getIds()) || StringUtils.isEmpty(bean.getType())) {
            throw new AppException(ResultCode.PARAM_ERROR.getMsg());
        }
        return communityDataCheckByType(bean.getIds(), bean.getType());
    }

    @Override
    @Aop(TransAop.READ_COMMITTED)
    public void report(SqfwDataMangeCheckVO bean) {
        if (null == bean) {
            throw new AppException(ResultCode.PARAM_ERROR.getMsg());
        }
        Sqfw_datamange_district_check sqfwDatamangeDistrictCheck = new Sqfw_datamange_district_check();
        BeanUtil.copyProperties(bean, sqfwDatamangeDistrictCheck);
        Sys_user sysUser = sysUserService.fetch(SecurityUtil.getUserId());
        sqfwDatamangeDistrictCheck
                .setSqfwSummaryId(bean.getSqfwSummaryId())
                .setProvince(sysUser.getProvince())
                .setCity(sysUser.getCity())
                .setDistrict(sysUser.getDistrict())
                .setCounty(sysUser.getCounty())
                .setCommunity(sysUser.getCommunity())
                .setCreateBy(sysUser.getId())
                .setCreateUserName(sysUser.getUsername())
                .setDelFlag(false)
                .setUnitId(sysUser.getUnitId())
                .setUnitName(sysUser.getUnitName())
                .setType(bean.getType())
                .setExcelData(CommunityDataCleanUtils.filtJsonArraySubData(bean.getExcelData(), "_time"))
                .setCreateDate(new Date());
        if (StringUtils.isNotEmpty(sqfwDatamangeDistrictCheck.getExcelData())) {
            JSONArray jsonArray = JSONUtil.parseArray(sqfwDatamangeDistrictCheck.getExcelData());
            sqfwDatamangeDistrictCheck.setRowNum(String.valueOf(jsonArray.size() - 1));
        }
        insert(sqfwDatamangeDistrictCheck);

        // 如果上一级主表没有对应数据，则插入， 如果有则更新上报的字段
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        try {
            CompletableFuture.runAsync(() -> {
                updateOrInsertMainTable(bean, sqfwDatamangeDistrictCheck, sysUser);
            }, executorService);
        } catch (Exception ex) {
            log.error(ex.getMessage());
        } finally {
            executorService.shutdown();
        }
    }

    /**
     * 如果上一级主表没有对应数据，则插入， 如果有则更新上报的字段
     */
    private void updateOrInsertMainTable(SqfwDataMangeCheckVO bean, Sqfw_datamange_district_check sqfwDatamangeDistrictCheck, Sys_user sysUser) {
        Sqfw_datamange_district sqfwDatamangeDistrict = new Sqfw_datamange_district();
        BeanUtil.copyProperties(sqfwDatamangeDistrictCheck, sqfwDatamangeDistrict);
        String excelData = sqfwDatamangeDistrict.getExcelData().replaceAll("#595FE0", "#FFFFFF").replaceAll("#FFFAFA", "#000000");

        // 查询详情,如果有记录则更新，否则插入新纪录
        SqfwDataMangeVO sqfwDataMangeVO = new SqfwDataMangeVO();
        sqfwDataMangeVO.setSqfwSummaryId(bean.getSqfwSummaryId());
        Sqfw_datamange_city sqfwDatamangeCityDetail = dataMangeCityService.fetch(Cnd.where("sqfw_summary_id", "=", bean.getSqfwSummaryId()));
        if (null != sqfwDatamangeCityDetail) {
            dataMangeCityService.update(Chain.make("excel_data", excelData), Cnd.where("sqfw_summary_id", "=", bean.getSqfwSummaryId()));
        } else {
            sqfwDatamangeDistrict
                    .setSqfwSummaryId(bean.getSqfwSummaryId())
                    .setProvince(sysUser.getProvince())
                    .setCity(sysUser.getCity())
                    .setDistrict(sysUser.getDistrict())
                    .setCounty(sysUser.getCounty())
                    .setCommunity(sysUser.getCommunity())
                    .setCreateBy(sysUser.getId())
                    .setCreateUserName(sysUser.getUsername())
                    .setDelFlag(false)
                    .setUnitId(sysUser.getUnitId())
                    .setUnitName(sysUser.getUnitName())
                    .setType(bean.getType())
                    .setCreateDate(new Date());
            sqfwDatamangeDistrict.setExcelData(sqfwDatamangeDistrict.getExcelData().replaceAll("#595FE0", "#FFFFFF").replaceAll("#FFFAFA", "#000000"));
            batchParseExcelJsonInsert(sqfwDatamangeDistrict);
        }
    }

    /**
     * 批量插入excel解析后的数据到主表
     *
     * @param sqfwDatamangeDistrict
     */
    private void batchParseExcelJsonInsert(Sqfw_datamange_district sqfwDatamangeDistrict) {
        if (null == sqfwDatamangeDistrict) {
            throw new AppException(ResultCode.NULL_DATA_ERROR.getMsg());
        }
        String excelData = sqfwDatamangeDistrict.getExcelData();
        try {
            JSONArray jsonArray = JSONUtil.parseArray(excelData);
            for (int i = 0; i < jsonArray.size(); i++) {
                Sqfw_datamange_district sqfwDatamangeDistrict1 = dataMangeDistrictService.fetch(Cnd.where("type", "=", sqfwDatamangeDistrict.getType()).limit(1));
                if (ObjectUtils.isNotEmpty(sqfwDatamangeDistrict1) && (0 == i)) {
                    continue;
                }
                Sqfw_datamange_city sqfwDatamangeCity1 = new Sqfw_datamange_city();
                BeanUtil.copyProperties(sqfwDatamangeDistrict, sqfwDatamangeCity1);
                Map<String, Map<String, String>> resultMap = new HashMap<String, Map<String, String>>();
                String excelDataNew = CommunityDataCleanUtils.parseExcelJsonForMainTable(jsonArray.get(i).toString(), resultMap);
                sqfwDatamangeCity1.setExcelData(JSONUtil.toJsonStr(excelDataNew));
                sqfwDatamangeCity1.setExcelSeg("body");
                if (0 == i) {
                    sqfwDatamangeCity1.setExcelSeg("header");
                }
                dataMangeCityService.insert(sqfwDatamangeCity1);
            }
        } catch (Exception ex) {
            log.error("街道to区县主表解析json异常, {}" + excelData);
        }
    }

    private SqfwDataMangeCheckVO communityDataCheckByType(List<String> ids, String type) {
        if (ObjectUtils.isEmpty(ids) || StringUtils.isEmpty(type)) {
            throw new AppException(ResultCode.PARAM_ERROR.getMsg());
        }
        List<Sqfw_datamange_district> sqfwDatamangeDistricts = dataMangeDistrictService.query(Cnd.where("id", "IN", ids));
        // 获取所有相关数据字段
        sqfwDatamangeDistricts.forEach(sqfwDatamangeDistrict -> {
            sqfwDatamangeDistrict.getExcelData();
        });

        // 插入表
        Sys_user sysUser = sysUserService.fetch(SecurityUtil.getUserId());
        Sqfw_datamange_street_check sqfwDatamangeStreetCheck = new Sqfw_datamange_street_check();
        sqfwDatamangeStreetCheck
                .setId(R.UU32())
                .setProvince(sysUser.getProvince())
                .setCity(sysUser.getCity())
                .setDistrict(sysUser.getDistrict())
                .setCounty(sysUser.getCounty())
                .setCommunity(sysUser.getCommunity())
                .setCreateBy(sysUser.getId())
                .setCreateUserName(sysUser.getUsername())
                .setDelFlag(false)
                .setUnitId(sysUser.getUnitId())
                .setUnitName(sysUser.getUnitName())
                .setType(type);
        StringBuffer sb = new StringBuffer();
       /* sqfwFormSummaryOnlines.forEach(sqfwDatamangeCommunity -> {
            sb.append(sqfwDatamangeCommunity.getExcelData()).append(",");
        });*/
        String excelDataAll = "[" + sb.substring(0, sb.lastIndexOf(",")) + "]";
        sqfwDatamangeStreetCheck.setExcelData(JSONUtil.toJsonStr(excelDataAll));
        SqfwDataMangeCheckVO sqfwDataMangeCheckVO = new SqfwDataMangeCheckVO();
        BeanUtil.copyProperties(sqfwDatamangeStreetCheck, sqfwDataMangeCheckVO);
        return sqfwDataMangeCheckVO;
    }

    /**
     * 组件excel数据,并插入数据库
     */
    private void buildExcelData(List<SqfwFormSummaryOnlineDTO> onlineList, List<Sqfw_datamange_community> sqfwFormSummaryOnlines, String type) {
        String commonId = R.UU32();
        ThreadPoolExecutor threadPoolExecutor = ThreadPoolExecutorUtil.getInstance();
        CompletableFuture[] cf = onlineList.stream().map(item -> CompletableFuture.runAsync(() ->
                        processExcelData(item, sqfwFormSummaryOnlines, commonId, type), threadPoolExecutor)
                .thenApplyAsync(r -> r)).toArray(CompletableFuture[]::new);
        CompletableFuture.allOf(cf).join();
        log.info("===========================组装Excel报文完成：{}条===========================", sqfwFormSummaryOnlines.size());
       /* onlineList.forEach(item->{
            processExcelData(item, rowCount, numCount, commonId, sqfwOnlineService);
        });*/
    }

    /**
     * 处理excel数据
     */
    private void processExcelData(SqfwFormSummaryOnlineDTO sqfwFormSummaryOnlineDTO, List<Sqfw_datamange_community> sqfwFormSummaryOnlines,
                                  String commonId, String type) {
        //synchronized (LOCK) {
        List<SqfwExcelOnlineAllDTO> sqfwExcelOnlineAllDTOS = Collections.synchronizedList(new ArrayList<SqfwExcelOnlineAllDTO>());
        String updateDate = CommunityDataCleanUtils.formatDate(String.valueOf(sqfwFormSummaryOnlineDTO.getCreateDate()));
        AtomicInteger colCount = new AtomicInteger(0);
        for (ConcurrentSkipListMap.Entry<String, String> entry : sqfwFormSummaryOnlineDTO.getExcelDataMap().entrySet()) {
            // 解析到excelJson
            SqfwExcelOnlineAllDTO sqfwExcelOnlineAllDTO = new SqfwExcelOnlineAllDTO();
            sqfwExcelOnlineAllDTO = CommunityDataCleanUtils.parseSummaryData(entry, updateDate);
            sqfwExcelOnlineAllDTOS.add(sqfwExcelOnlineAllDTO);
            sqfwFormSummaryOnlineDTO.setExcelData(JSONUtil.toJsonStr(sqfwExcelOnlineAllDTOS));
            colCount.getAndIncrement();
        }
        sqfwFormSummaryOnlineDTO.setColNum(String.valueOf(colCount.get()));
        log.info("============id:{}, 总列数：{}============", sqfwFormSummaryOnlineDTO.getSqfwSummaryId(), colCount.getAndIncrement());
        sqfwFormSummaryOnlineDTO.setCommonId(commonId);
        sqfwFormSummaryOnlineDTO.setId(R.UU32());
        sqfwFormSummaryOnlineDTO.setDelFlag(false);
        sqfwFormSummaryOnlineDTO.setSqfwSummaryId(sqfwFormSummaryOnlineDTO.getSqfwSummaryId());
        if (StringUtils.isEmpty(sqfwFormSummaryOnlineDTO.getSqfwSummaryId())) {
            sqfwFormSummaryOnlineDTO.setExcelSeg("header");
        } else {
            sqfwFormSummaryOnlineDTO.setExcelSeg("body");
        }
        if (StringUtils.isNotEmpty(type)) {
            sqfwFormSummaryOnlineDTO.setType(type);
        }
        sqfwFormSummaryOnlines.add(sqfwFormSummaryOnlineDTO);
        //}
    }

    /**
     * 将清洗好的Excel数据插入数据库
     */
    @Aop(TransAop.READ_COMMITTED)
    @CacheRemove
    private void excelDataBatchInsert(List<Sqfw_datamange_community> onlineList) {
        ThreadPoolExecutor threadPoolExecutor = ThreadPoolExecutorUtil.getInstance();
        CompletableFuture[] cf = onlineList.stream().map(item -> CompletableFuture.runAsync(() ->
                        this.insert(item), threadPoolExecutor)
                .thenApplyAsync(r -> r)).toArray(CompletableFuture[]::new);
        CompletableFuture.allOf(cf).join();
    }

    /**
     * 构造查询条件
     *
     * @param bean
     * @return
     */
    private Criteria buildQueryCond(SqfwDataMangeCheckVO bean) {
        Criteria cri = Cnd.cri();
        SqlExpressionGroup criSql = cri.where();
        // 不查询excel头
        criSql.andNotEquals(Sqfw_datamange_community::getExcelSeg, "header");
        criSql.andEquals(Sqfw_datamange_community::getDelFlag, false);
        if (null != bean && StringUtils.isNotEmpty(bean.getPlaceType())) {
            criSql.andLike("param_data->>'placeType'", bean.getPlaceType());
        }
        if (null != bean && StringUtils.isNotEmpty(bean.getCommunity())) {
            criSql.andLike(Sqfw_datamange_community::getCommunity, bean.getCommunity());
        }
        return cri;
    }
}
